/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
package org.unidata.mdm.rest.v1.dq.core.converter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.unidata.mdm.dq.core.type.model.source.rule.InputPortMapping;
import org.unidata.mdm.dq.core.type.model.source.rule.OutputPortMapping;
import org.unidata.mdm.dq.core.type.model.source.rule.RuleMappingSource;
import org.unidata.mdm.rest.system.converter.Converter;
import org.unidata.mdm.rest.v1.dq.core.ro.rule.PortMappingRO;
import org.unidata.mdm.rest.v1.dq.core.ro.rule.RuleMappingRO;

/**
 * @author Mikhail Mikhailov on Mar 4, 2021
 */
public class RuleMappingConverter extends Converter<RuleMappingSource, RuleMappingRO> {
    /**
     * The CC.
     */
    private static final ConstantConverter CONSTANT_CONVERTER = new ConstantConverter();
    /**
     * Constructor.
     * @param to
     * @param from
     */
    public RuleMappingConverter() {
        super(RuleMappingConverter::convert, RuleMappingConverter::convert);
    }

    private static RuleMappingRO convert(RuleMappingSource source) {

        RuleMappingRO target = new RuleMappingRO();

        target.setRuleName(source.getRuleName());
        target.setLocalPath(source.getLocalPath());
        target.setInputs(toInputs(source.getInputMappings()));
        target.setOutputs(toOutputs(source.getOutputMappings()));

        return target;
    }

    /**
     * Map inputs.
     *
     * @param source
     *            the source
     * @param target
     *            the target
     */
    private static List<PortMappingRO> toInputs(List<InputPortMapping> source) {

        if (CollectionUtils.isEmpty(source)) {
            return Collections.emptyList();
        }

        List<PortMappingRO> target = new ArrayList<>();
        for (InputPortMapping m : source) {

            if (StringUtils.isBlank(m.getPortName())) {
                continue;
            }

            PortMappingRO mapping = new PortMappingRO();
            mapping.setPortName(m.getPortName());
            mapping.setPath(m.getInputPath());
            mapping.setConstant(CONSTANT_CONVERTER.to(m.getConstantValue()));

            target.add(mapping);
        }

        return target;
    }

    /**
     * Map outputs.
     *
     * @param source
     *            the source
     * @param target
     *            the target
     */
    private static List<PortMappingRO> toOutputs(List<OutputPortMapping> source) {

        if (CollectionUtils.isEmpty(source)) {
            return Collections.emptyList();
        }

        List<PortMappingRO> target = new ArrayList<>();
        for (OutputPortMapping m : source) {

            if (StringUtils.isBlank(m.getPortName())) {
                continue;
            }

            PortMappingRO mapping = new PortMappingRO();
            mapping.setPath(m.getOutputPath());
            mapping.setPortName(m.getPortName());
            mapping.setConstant(CONSTANT_CONVERTER.to(m.getConstantValue()));

            target.add(mapping);
        }

        return target;
    }

    private static RuleMappingSource convert(RuleMappingRO source) {
        return new RuleMappingSource()
                .withRuleName(source.getRuleName())
                .withExecutionPath(source.getLocalPath())
                .withInputMappings(fromInputs(source.getInputs()))
                .withOutputMappings(fromOutputs(source.getOutputs()));
    }

    /**
     * Map inputs.
     *
     * @param source
     *            the source
     * @param target
     *            the target
     */
    private static List<InputPortMapping> fromInputs(List<PortMappingRO> source) {

        if (CollectionUtils.isEmpty(source)) {
            return Collections.emptyList();
        }

        List<InputPortMapping> target = new ArrayList<>();
        for (PortMappingRO m : source) {

            if (StringUtils.isBlank(m.getPortName())) {
                continue;
            }

            target.add(new InputPortMapping()
                .withInputPath(m.getPath())
                .withPortName(m.getPortName())
                .withConstantValue(CONSTANT_CONVERTER.from(m.getConstant())));
        }

        return target;
    }
    /**
     * Map outputs.
     *
     * @param source
     *            the source
     * @param target
     *            the target
     */
    private static List<OutputPortMapping> fromOutputs(List<PortMappingRO> source) {

        if (CollectionUtils.isEmpty(source)) {
            return Collections.emptyList();
        }

        List<OutputPortMapping> target = new ArrayList<>();
        for (PortMappingRO m : source) {

            if (StringUtils.isBlank(m.getPortName())) {
                continue;
            }

            target.add(new OutputPortMapping()
                    .withOutputPath(m.getPath())
                    .withPortName(m.getPortName())
                    .withConstantValue(CONSTANT_CONVERTER.from(m.getConstant())));
        }

        return target;
    }
}
